
#ifndef _TTG_THREADS_DEFAULT_THREAD_POOL_
#define _TTG_THREADS_DEFAULT_THREAD_POOL_
#include "Common/Definitions.h"

#include "Threads.h"
#include "ThreadPool.h"

namespace ttg_internal
{
	namespace threads
	{
		//Represents perfromer logic.
		//Thread::tag is used for performer number.
		class Performer :public ttg::threads::Thread
		{
			private:
				ttg::structures::RetLoopback<Task *,
											 Performer *> on_idle;		//Notifies, that tasks has been performed.
				std::vector<Task *> tasks;								//List with all tasks.
				ttg::threads::FastCriticalSection tasks_locker;			//Locker for tasks.
				std::vector<Task *> local_tasks;						//Tasks, that was produced by performed tasks.
				bool is_gonna_sleep;									//Is performer going to sleep?
				ttg::threads::FastCriticalSection is_gonna_sleep_locker;
			protected:
				//Returns following task (or NULL) [thread safe].
				Task *getTask_ts();
				//Version of sleep, that will resleep after n ms.
				void wiseSleep();
				//Thread member.
				virtual void work();
			public:
				//Creates performer for pool.
				Performer(size_t core);
				//Returns true, if performer is idle.
				bool isIdle();
				//Returns idle event.
				//Event arg == thread ID of idle performer.
				inline ttg::structures::RetLoopback<Task *, Performer *> &onIdle()
				{ return on_idle; }
				//Adds tasks for current performer and (optionally) wakes performer.
				void addTask(Task *task);
				virtual ~Performer();
		};
		//Default implementation of thread pool (via threads::Thread).
		//Can be used instead of native implementation.
		class DefaultThreadPool :public ThreadPool
		{
			private:
				std::vector<Performer *> performers;
				std::vector<Task *> untaken_tasks;
				ttg::threads::FastCriticalSection untaken_tasks_locker;
			private:
				static Task *onIdlePerformer(DefaultThreadPool *owner, Performer *smoker);
				//Distributes given tasks between sleeping performers.
				//Untaken tasks will be left in vector.
				void distributeBetweenSleepers(std::vector<Task *> &tasks);
				//Tries to give untaken task to performer [thread safe].
				//If such task exists, returns true (false otherwise).
				bool giveTaskTo_ts(Performer *performer);
			public:
				//Creates pool with required performers.
				DefaultThreadPool(size_t performer_count);
				//Returns count of smokers.
				virtual size_t getIdlePerformerCount();
				//Adds tasks explicitly [thread-safe].
				virtual void addTasks(ttg::structures::Enumerator<Task *> &tasks);
				//For descendant only.
				virtual ~DefaultThreadPool();
		};
	}
}

#endif
